package main

import (
	"fmt"
	"go-xorm-01/utils"
	"time"
	"xorm.io/xorm"
	"xorm.io/xorm/log"
	"xorm.io/xorm/names"
)

var engine *xorm.Engine

// 查询条件方法 :https://xorm.io/zh/docs/chapter-05/1.conditions/
// 查询和统计数据
// 所有的查询条件不区分调用顺序，但必须在调用Get，Exist, Sum, Find，Count, Iterate, Rows这几个函数之前调用。
// 同时需要注意的一点是，在调用的参数中，如果采用默认的SnakeMapper所有的字符字段名均为映射后的数据库的字段名，而不是field的名字。
//
// 查询条件方法
// 查询和统计主要使用Get, Find, Count, Rows, Iterate这几个方法，同时大部分函数在调用Update, Delete时也是可用的。
// 在进行查询时可以使用多个方法来形成查询条件，
func main() {
	SnakeMapper()
	//insetManyUser(engine)
	//engine.DumpAllToFile("demo05-query/demo01-querywhere/sql.sql")
	queryUser(engine)
}

func queryUser(engine *xorm.Engine) {
	//给Table设定一个别名 Alias(string)
	var userQ UserQuery
	_, err := engine.Alias("u").Where("u.id = ?", 2).Get(&userQ)
	if err != nil {
		panic(err)
	}
	fmt.Println("根据id条件查询：=", userQ)

	var userQ2 UserQuery
	_, err = engine.Alias("u").Where("u.id = ?", 2).And("u.username = ?", "zhangsan-1").Get(&userQ2)
	if err != nil {
		panic(err)
	}
	fmt.Println("根据id和username查询：=", userQ2)

	var userQ3 []UserQuery
	err = engine.Alias("u").Where("u.id > ?", 2).Asc("u.id").Find(&userQ3)
	if err != nil {
		panic(err)
	}
	fmt.Println("根据id排序查询：")
	for _, user := range userQ3 {
		fmt.Printf("%d\n", user.Id)
	}

	var userQ4 UserQuery
	_, err = engine.ID(4).Get(&userQ4)
	if err != nil {
		panic(err)
	}
	fmt.Println("根据ID主键查询：=", userQ4)

	var userQ5 []UserQuery
	//err = engine.In("id", 1, 2, 3, 4, 5).Find(&userQ5)
	err = engine.In("id", []int{1, 2, 3}).Find(&userQ5)
	if err != nil {
		panic(err)
	}
	fmt.Println("根据in查询：", userQ5)

	var userQ6 []UserQuery
	err = engine.Cols("id", "username").In("id", []int{1, 2, 3}).Find(&userQ6)
	fmt.Println("指定字段名查询：", userQ6)

	//AllCols()
	//查询或更新所有字段，一般与Update配合使用，因为默认Update只更新非0，非""，非bool的字段。
	//
	//engine.AllCols().ID(1).Update(&user)
	//// UPDATE user SET name = ?, age =?, gender =? WHERE id = 1
	//MustCols(…string)
	//某些字段必须更新，一般与Update配合使用。
	//
	//Omit(…string)
	//和cols相反，此函数指定排除某些指定的字段。注意：此方法和Cols方法不可同时使用。

	var userQ7 []UserQuery
	err = engine.Distinct("username", "groupId").Find(&userQ7)
	fmt.Println("Distinct查询：", userQ7)

	var userQ8 []UserQuery
	err = engine.Limit(3, 0).Asc("id").Find(&userQ8)
	fmt.Println("Limit查询：", userQ8)

	var userQ9 []UserQuery
	err = engine.GroupBy("group_id").Find(&userQ9)
	fmt.Println("GroupBy查询：", userQ9)
}

func SnakeMapper() {
	engine = utils.GenerateEngine()
	engine.SetMapper(names.SnakeMapper{}) // SnakeMapper 【默认】
	err := engine.Sync2(new(UserQuery))
	if err != nil {
		fmt.Printf("err:%v", err)
	}
	engine.ShowSQL(true)
	engine.SetLogLevel(log.LOG_DEBUG)

}

func insetManyUser(engine *xorm.Engine) {
	groupOne := make([]*UserQuery, 0)
	for i := 0; i < 5; i++ {
		groupOne = append(groupOne, &UserQuery{
			Username: fmt.Sprintf("zhangsan-%d", i),
			Password: fmt.Sprintf("123456-%d", i),
			GroupId:  1,
			Rank:     i,
		})
	}
	engine.Insert(groupOne)

	groupTwo := make([]*UserQuery, 0)
	for i := 0; i < 3; i++ {
		groupTwo = append(groupTwo, &UserQuery{
			Username: fmt.Sprintf("lisi-%d", i),
			Password: fmt.Sprintf("00000-%d", i),
			GroupId:  2,
			Rank:     i,
		})
	}
	engine.Insert(groupTwo)

}

type JsonTime time.Time

func (j JsonTime) MarshalJSON() ([]byte, error) {
	return []byte(`"` + time.Time(j).Format("2006-01-02 15:04:05") + `"`), nil
}

type UserQuery struct {
	Id        int64     `xorm:"pk autoincr"`                                              //指定列名 ，默认id
	Username  string    `xorm:"varchar(25) notnull unique(u_p) 'username' comment('姓名')"` //复合唯一索引
	Password  string    `xorm:"varchar(25) notnull unique(u_p) 'password' comment('密码')"` //复合唯一索引
	TimeOne   time.Time `xorm:"created"`
	TimeTwo   JsonTime  `xorm:"created"`
	TimeThree int64     `xorm:"created"`
	GroupId   int64
	Rank      int
}
